﻿using DeviceAlarmService.Models.SiemensPlc;
using S7.Net;
using S7.Net.Types;

namespace DeviceAlarmService.DeviceManagement.DeviceConnection.SiemensPlc;

public class ConnectingObjects
{
    Plc plc;

    DeviceInformation device;


    /// <summary>
    /// Plc连接状态
    /// </summary>
    public bool IsConnected
    {
        get
        {
            if (plc is not null)
            {
                return plc.IsConnected;
            }
            return false;
        }
    }

    public ConnectingObjects(DeviceInformation deviceInformation)
    {
        this.device = deviceInformation;
    }

    /// <summary>
    /// 构建plc连接
    /// </summary>
    /// <param name="device"></param>
    /// <returns></returns>
    public void Connect()
    {
        try
        {
            DeviceAddress deviceAddress = device.deviceAddress;

            plc = new(deviceAddress.cpuType, deviceAddress.ip, deviceAddress.port, deviceAddress.rack, deviceAddress.slot);

            plc.Open();
        }
        catch (Exception ex)
        {
            plc = null;
            throw new Exception(ex.Message);
        }
    }

    //分页数据
    private List<List<DataItem>> pages = null;
    //获取数据地址
    private List<string> addr = null;
    /// <summary>
    ///读取Bool值 
    /// </summary>
    /// <param name="plc"></param>
    /// <param name="addr"></param>
    /// <returns></returns>
    public List<bool> ReadBool()
    {
        //报警结果列表
        List<bool> result = new List<bool>();
        //检查报警地址是否存在
        if (addr is null)
        {
            addr = new();

            foreach (var item in device.dataAddress)
            {
                addr.Add(item.alarmAddress);
            }
        }

        //是否批量读取
        if (device.deviceAddress.isMultiple)
        {
            if (pages is null)
            {
                //获取数据地址
                List<DataItem> data = new List<DataItem>();
                foreach (var item in addr)
                {
                    data.Add(DataItem.FromAddress(item));
                }
                // 将一维列表按长度分页  
                pages = PaginateList(data, 16);
            }
            // 输出分页结果  
            foreach (var page in pages)
            {
                //批量读取
                plc.ReadMultipleVars(page);

                //遍历结果
                foreach (var item in page)
                {
                    result.Add((bool)item.Value);
                }
            }
        }
        else
        {
            foreach (var item in addr)
            {
                result.Add((bool)plc.Read(item));
                Thread.Sleep(1);
            }
        }

        return result;
    }

    static List<List<T>> PaginateList<T>(List<T> list, int pageSize)
    {
        return list
            .Select((item, index) => new { item, index })
            .GroupBy(x => x.index / pageSize)
            .Select(x => x.Select(v => v.item).ToList())
            .ToList();
    }

    /// <summary>
    /// 关闭plc连接
    /// </summary>
    /// <param name="plc"></param>
    public void Close()
    {
        if (plc is not null)
        {
            plc.Close();
        }
    }
}